using System;
using System.Linq;
using System.Runtime.Serialization;


namespace FoundationLib.Ifc.Exceptions 
{
	/// <summary>
	/// This class can be used by business services to throw business-related and non-
	/// technical exceptions.
	/// </summary>
	[Serializable]
	public class BusinessException : Exception, ISerializable 
	{
		/// <summary>
		/// The exception code
		/// </summary>
		private int code = 0;


		/// <summary>
		/// Gets the exception code. The default is 0.
		/// </summary>
		public int Code
		{
			get
			{
				return this.code;
			}
		}

		/// <summary>
		/// Creates a new <see cref="BusinessException"/>.
		/// </summary>
		public BusinessException()
			: base()
		{
		}

		/// <summary>
		/// Creates a new <see cref="BusinessException"/>.
		/// </summary>
		/// <param name="message">The exception message</param>
		public BusinessException(string message)
			: base(message)
		{
		}

		/// <summary>
		/// Creates a new <see cref="BusinessException"/>.
		/// </summary>
		/// <param name="message">The exception message</param>
		/// <param name="code">The exception code</param>
		public BusinessException(string message, int code)
			: base(message)
		{
			this.code = code;
		}

		/// <summary>
		/// Creates a new <see cref="BusinessException"/>.
		/// </summary>
		/// <param name="message">The exception message</param>
		/// <param name="parameters">The parameters to replace</param>
		public BusinessException(string message, params object[] parameters)
			: base(String.Format(message, parameters))
		{
		}

		/// <summary>
		/// Creates a new <see cref="BusinessException"/>.
		/// </summary>
		/// <param name="message">The exception message</param>
		/// <param name="code">The exception code</param>
		/// <param name="parameters">The parameters to replace</param>
		public BusinessException(string message, int code, params object[] parameters)
			: base(String.Format(message, parameters))
		{
			this.code = code;
		}

		/// <summary>
		/// Creates a new <see cref="BusinessException"/>.
		/// </summary>
		/// <param name="message">The exception message</param>
		/// <param name="innerException">The inner exception</param>
		/// <param name="parameters">The parameters to replace in the exception message</param>
		public BusinessException(string message, Exception innerException, params object[] parameters)
			: base(String.Format(message, parameters), innerException)
		{
		}

		/// <summary>
		/// Creates a new <see cref="BusinessException"/>.
		/// </summary>
		/// <param name="message">The exception message</param>
		/// <param name="innerException">The inner exception</param>
		/// <param name="code">The exception code</param>
		/// <param name="parameters">The parameters to replace in the exception message</param>
		public BusinessException(string message, int code, Exception innerException, params object[] parameters)
			: base(String.Format(message, parameters), innerException)
		{
			this.code = code;
		}

		/// <summary>
		/// Creates a new <see cref="BusinessException"/>.
		/// </summary>
		/// <param name="message">The exception message</param>
		/// <param name="innerException">The inner exception</param>
		public BusinessException(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		/// <summary>
		/// Creates a new <see cref="BusinessException"/>.
		/// </summary>
		/// <param name="message">The exception message</param>
		/// <param name="code">The exception code</param>
		/// <param name="innerException">The inner exception</param>
		public BusinessException(string message, int code, Exception innerException)
			: base(message, innerException)
		{
			this.code = code;
		}

		/// <summary>
		/// Creates a new <see cref="BusinessException"/>.
		/// </summary>
		/// <param name="context">The streaming context</param>
		/// <param name="info">The serialisation information</param>
		protected BusinessException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		/// <see cref="ISerializable.GetObjectData(SerializationInfo, StreamingContext)"/>
		public override void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			base.GetObjectData(info, context);
			info.AddValue("code", this.code);
		}
	}

}